package com.bgds.sys.data.iXCom29d.gateway.impl;

import cn.hutool.core.io.file.FileWriter;
import com.alibaba.fastjson.JSON;
import com.bgds.sys.api.service.BaoXinService;
import com.bgds.sys.common.utils.HexUtil;
import com.bgds.sys.common.utils.SpringUtil;
import com.bgds.sys.data.iXCom29d.protocol.utils.IXComActionParamDTO;
import com.bgds.sys.util.DianwenData;
import com.cisdi.data.common.exception.BusinessException;
import com.cisdi.data.sdk.consts.ServiceName;
import com.cisdi.data.sdk.gateway.message.SocketMessage;
import com.cisdi.data.sdk.gateway.netty.IoSession;
import com.cisdi.data.sdk.gateway.netty.impl.AbstractIoSession;
import com.cisdi.data.sdk.service.DynamicCodecService;
import com.cisdi.data.sdk.service.PassthroughService;
import com.cisdi.data.sdk.service.SendService;
import io.netty.buffer.ByteBuf;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.charset.Charset;
import java.util.Optional;

/**
 * 宝信29d通信session
 * @author cup
 *
 */
public class BaoXingSession extends AbstractIoSession implements IoSession {


	private long lastAliveTime = System.currentTimeMillis();

	private static Logger logger = LoggerFactory.getLogger(BaoXingSession.class);

	private String deviceId = null;
	private Charset charset;

	public BaoXingSession(String deviceId, Charset charset) {
		super();
		this.deviceId = deviceId;
		this.charset = charset;
	}

	@Override
	public void onRead(Object message) {
		ByteBuf inBuf = ((ByteBuf)message);
		int length = inBuf.readableBytes();
//		byte[] bytes=new byte[length];
//		inBuf.readBytes(bytes);
//		inBuf.resetReaderIndex();
//		DianwenData.appendMessage(getChannel().localAddress().toString(),bytes);
		BaoXingVo dataAck = null;
		BaoXingVo vo = null;
		Integer readerIndex = null;

		try {
			// 预备处理透传
			if(socketGateway != null && Boolean.TRUE.equals(socketGateway.getInstanceVo().getNeedPassthrough())) {
				readerIndex = inBuf.readerIndex();
			}

			vo = BaoXingVoDecode.decode(inBuf, Charset.defaultCharset());
			Boolean flag=socketGateway != null && Boolean.TRUE.equals(socketGateway.getInstanceVo().getLogOpen());
			if(socketGateway == null || flag) {
				logger.info("宝信29d {} 报文长度:{} vo:{} ", getChannel(), length,  "过长暂不展示");
			}
			// 应该只有数据报文，如果混入了其他报文，则报错
			if(BaoXingConsts.FUNC_CODE_DATA.equals(vo.getFuncCode()) == false) {
				throw new BusinessException("not supported funcCode:" + vo.getFuncCode() + "should be:" + BaoXingConsts.FUNC_CODE_DATA);
			}
			// 普通数据报文
			if(vo != null){
				BaoXinService baoXinService=SpringUtil.getBean(BaoXinService.class);
				//解析和保存报文数据到mysql数据库和时序数据库
				baoXinService.analysisMessage(vo);
			}
			if(vo != null && serviceProvider != null && socketGateway != null){
				SendService service = (SendService)serviceProvider.getByName(ServiceName.Send);
				SocketMessage socketMessage = socketGateway.buildSocketMessage();
				socketMessage.setDeviceId(this.deviceId);
				socketMessage.setMsgKey(vo.getMsgKey());
				socketMessage.setData(vo.getData());
				socketMessage.getPropsMap().put("charset", charset.name());
				logger.info("宝信29d socketMessage{} ", socketMessage);
				service.sendMessage(socketMessage);
			}

			dataAck = BoBuilder.dataAckSuccess(vo.getMsgKey(), vo.getReceiveDc(), vo.getSendDc());
		} catch (Exception e) {
			logger.error(e.getLocalizedMessage(), e);
			dataAck = BoBuilder.dataAckFail(vo.getMsgKey(), vo.getSendDc(), vo.getReceiveDc(), e.getLocalizedMessage());
		}finally {
			// 发送响应报文
			getChannel().writeAndFlush(dataAck);
			// 需要透传
			if(readerIndex != null) {
				inBuf.readerIndex(readerIndex);
				passthrough(inBuf, vo);
			}
		}

	}
	private void passthrough(ByteBuf passthroughBuf, BaoXingVo vo) {
		try {
			if(serviceProvider != null && socketGateway != null && vo != null) {
				// 验证电文key，如果匹配则透传
				DynamicCodecService codecService = (DynamicCodecService)serviceProvider.getByName(ServiceName.DynamicCodec);
				if (codecService == null || !(codecService instanceof DynamicCodecService)) {
					throw new BusinessException("获取JsonCodecService失败");
				}

				String paramObj = codecService.findByRunIdAndMsgKey(socketGateway.getInstanceVo().getRunId(), vo.getMsgKey());
				IXComActionParamDTO dto = JSON.parseObject(paramObj, IXComActionParamDTO.class);
				if(dto != null && Boolean.TRUE.equals(dto.getIsPassthrough())) {
					PassthroughService service = (PassthroughService)serviceProvider.getByName(ServiceName.Passthrough);
					service.transfer(passthroughBuf, socketGateway.getInstanceVo().getPassthroughAddress());
				}
			}
		}catch (Exception e) {
			logger.error("iXCom29d透传失败：" + e.getLocalizedMessage(), e);
		}
	}

	@Override
	public void onOpen() {
		super.onOpen();
		logger.info("建立连接，channel:{}", getChannel());
	}

	@Override
	public void onClose() {
		super.onClose();
	}

	public void close() {
		if(getChannel() != null) {
			try {
				getChannel().close().sync();
			} catch (InterruptedException e) {
				logger.warn(e.getLocalizedMessage(), e);
			}
		}
	}

	private String gwPrefixCache = null;

	public String gwPrefix() {
		if(gwPrefixCache != null) {
			return gwPrefixCache;
		}

		gwPrefixCache = "";
		if(socketGateway != null && socketGateway.getInstanceVo() != null) {
			gwPrefixCache = "网关Id:" + socketGateway.getInstanceVo().getRunId() + "连接:" + getChannel() + " ";
		}else {
			gwPrefixCache = "连接:" + getChannel() + " ";
		}

		return gwPrefixCache;
	}

	public long getLastAliveTime() {
		return lastAliveTime;
	}

	public void setLastAliveTime(long lastAliveTime) {
		this.lastAliveTime = lastAliveTime;
	}

	@Override
	public String[] getDeviceIds() {
		String cpDeviceId = deviceId;
		String[] result = new String[cpDeviceId == null ? 0 : 1];
		if(cpDeviceId != null) {
			result[0] = cpDeviceId;
		}
		return result;
	}
}